#include <QDebug>
#include <QThread>
#include <QMutex>
#include "kaptilo.h"
//
//Сетевую ловушку нужно вызывать для каждого входящего пакета
void dispatcher_handler(u_char *arg, const struct pcap_pkthdr *header, const u_char *pkt_data){
	((KaptiloFunk*)arg)->Funk(header, pkt_data);
}

class NewThread : public QThread{
private:
	QString Device;
	QString Filter;
	KaptiloFunk * kf;
public:
	NewThread( const QString & d, const QString & f, KaptiloFunk * KF, QObject * parent = 0)
	:QThread(parent), Device(d), Filter(f), kf(KF){}
	void run(){
		// дескриптор адаптера
		pcap_t * fp;
		// буфер для хранения описания ошибок
		char error[PCAP_ERRBUF_SIZE];
		// описываем структуру
		struct bpf_program fcode;
	
		bpf_u_int32 SubNet,NetMask;	
		
		//начинаем процесс захвата пакетов из сети
		if (Device.toAscii().data() != NULL){
			if ( (fp= pcap_open_live(Device.toAscii().data(), 1514, 1, 20, error) ) == NULL){
				qDebug()<<trUtf8("Невозможно открыть адаптер.\n")
						+ QString::fromUtf8(error);
				return;
			}
		}else {
			qDebug()<<trUtf8("Указано неверное устройство");
			return;
		}
	
		if(Filter.toAscii().data()!=NULL){
	
			//получаем адрес подсети
			if(pcap_lookupnet(Device.toAscii().data(), &SubNet, &NetMask, error)<0){
				qDebug()<<trUtf8("Невозможно определить маску сети.\n")
									 + QString::fromUtf8(error);
				return;
			}
			else NetMask=0xffffff; //Если обрабатываем файл, подразумевается, что мы работаем с подсетью класса C
	
			//Компилируем фильтр
			if(pcap_compile(fp, &fcode, Filter.toAscii().data(), 1, NetMask)<0){
				qDebug()<<trUtf8("Ошибка компиляции фильтра: неверный синтаксис.\n")
															+ QString::fromUtf8(error);
				return;
			}
	
			//Устанавливаем откомпилированный фильтр
			if(pcap_setfilter(fp, &fcode)<0){
				qDebug()<<trUtf8("Ошибка при установке фильтра\n")
															+ QString::fromUtf8(error);
				return;
			}	
		}
	
		//Все готово – начало работы!!!
		pcap_loop(fp, -1, dispatcher_handler, (unsigned char *)kf);
		exec();

		// При остановке потока закрываю соединение.
		pcap_close(fp);
	}
};

//
Kaptilo::Kaptilo( const QString & device, const QString & filter, KaptiloFunk * kf, QObject * parent)
	: QObject(parent), th(new NewThread(device, filter, kf)){

//	qDebug()<<Device.toAscii().data();
	kf->setParent(this); 
	// Запускаю сниффер в новом потоке. Класс потока скрыт от пользователя.
	th->start();	
}
//
Kaptilo::~Kaptilo(){
	th->exit();
}
//
